// File: jmcomic-core/src/main/java/dev/jukomu/common/util/json/AdvancedMap.java
package dev.jukomu.common.util.json;

import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 功能增强版Map，对应Python的AdvancedDict。
 * 允许通过get方法链式获取嵌套值，并支持常用操作。
 */
public class AdvancedMap implements Map<String, Object> {

    private final Map<String, Object> data;

    public AdvancedMap(Map<String, Object> data) {
        Objects.requireNonNull(data, "Initialization parameter must not be null");
        this.data = data;
    }

    /**
     * 包装数据，如果是Map则包装为AdvancedMap。
     *
     * @param data 要包装的数据
     * @return 包装后的AdvancedMap或原始数据
     */
    public static AdvancedMap wrap(Object data) {
        if (data instanceof Map) {
            // Unchecked cast, assumes Map keys are String
            return new AdvancedMap((Map<String, Object>) data);
        }
        if (data instanceof AdvancedMap) {
            return (AdvancedMap) data;
        }
        throw new IllegalArgumentException("Unsupported type for wrap: " + data.getClass().getName());
    }

    /**
     * 包装值，如果是Map则递归包装为AdvancedMap，如果是List/Collection则包装其内部的Map。
     *
     * @param value 要包装的值
     * @return 包装后的值
     */
    public static Object wrapValue(Object value) {
        if (value instanceof Map) {
            // Unchecked cast, assumes Map keys are String
            return new AdvancedMap((Map<String, Object>) value);
        }
        if (value instanceof Collection) {
            return ((Collection<?>) value).stream()
                    .map(item -> item instanceof Map ? new AdvancedMap((Map<String, Object>) item) : item)
                    .collect(Collectors.toList());
        }
        return value;
    }

    /**
     * 获取原始Map。
     *
     * @return 原始Map
     */
    public Map<String, Object> getSrcMap() {
        return data;
    }

    // 代理Map的方法
    @Override
    public int size() {
        return data.size();
    }

    @Override
    public boolean isEmpty() {
        return data.isEmpty();
    }

    @Override
    public boolean containsKey(Object key) {
        return data.containsKey(key);
    }

    @Override
    public boolean containsValue(Object value) {
        return data.containsValue(value);
    }

    /**
     * 重写get方法，确保返回的值如果是Map，会被包装成AdvancedMap。
     */
    @Override
    public Object get(Object key) {
        return wrapValue(data.get(key));
    }

    /**
     * 获取指定键的值，如果不存在则返回默认值。
     *
     * @param key          键
     * @param defaultValue 默认值
     * @param <T>          返回类型
     * @return 值或默认值
     */
    @SuppressWarnings("unchecked")
    public <T> T get(String key, T defaultValue) {
        Object value = data.get(key);
        if (value == null) {
            return defaultValue;
        }
        // 使用wrapValue来确保嵌套Map被包装
        return (T) wrapValue(value);
    }

    /**
     * 获取指定键的值，并尝试转换为指定类型。
     *
     * @param key   键
     * @param clazz 目标类型Class
     * @param <T>   返回类型
     * @return 转换后的值，如果键不存在或转换失败则返回null
     */
    @SuppressWarnings("unchecked")
    public <T> T get(String key, Class<T> clazz) {
        Object value = data.get(key);
        if (value == null) {
            return null;
        }

        // 如果期望的类型是AdvancedMap，并且实际值是Map，则直接包装
        if (clazz == AdvancedMap.class && value instanceof Map) {
            return clazz.cast(new AdvancedMap((Map<String, Object>) value));
        }

        if (clazz.isInstance(value)) {
            return clazz.cast(value);
        }

        // 尝试进行基本类型转换
        if (clazz == Integer.class) {
            if (value instanceof Number) {
                return clazz.cast(((Number) value).intValue());
            }
            if (value instanceof String) {
                try {
                    return clazz.cast(Integer.parseInt((String) value));
                } catch (NumberFormatException e) {
                    return null;
                }
            }
        }
        if (clazz == Long.class) {
            if (value instanceof Number) {
                return clazz.cast(((Number) value).longValue());
            }
            if (value instanceof String) {
                try {
                    return clazz.cast(Long.parseLong((String) value));
                } catch (NumberFormatException e) {
                    return null;
                }
            }
        }
        if (clazz == Double.class) {
            if (value instanceof Number) {
                return clazz.cast(((Number) value).doubleValue());
            }
            if (value instanceof String) {
                try {
                    return clazz.cast(Double.parseDouble((String) value));
                } catch (NumberFormatException e) {
                    return null;
                }
            }
        }
        if (clazz == Boolean.class && value instanceof String) {
            return clazz.cast(Boolean.parseBoolean((String) value));
        }
        if (clazz == String.class) {
            return clazz.cast(String.valueOf(value));
        }

        // 如果无法直接转换，使用Jackson进行最后尝试
        try {
            return dev.jukomu.common.util.json.JsonUtils.parseString(dev.jukomu.common.util.json.JsonUtils.toJsonString(value), clazz);
        } catch (IOException e) {
            return null; // 转换失败
        }
    }

    /**
     * 链式获取嵌套Map中的值。
     *
     * @param keys 键路径
     * @param <T>  返回类型
     * @return 嵌套值
     * @throws IllegalArgumentException 如果路径中某个键对应的值不是Map
     */
    @SuppressWarnings("unchecked")
    public <T> T getNested(String... keys) {
        Map<String, Object> current = data;
        for (int i = 0; i < keys.length; i++) {
            String key = keys[i];
            Object value = current.get(key);
            if (value == null) {
                return null;
            }
            if (i == keys.length - 1) {
                return (T) wrapValue(value);
            }
            if (!(value instanceof Map)) {
                throw new IllegalArgumentException("Path element '" + key + "' is not a Map in path: " + String.join(".", keys));
            }
            current = (Map<String, Object>) value;
        }
        return (T) wrapValue(current); // Should not reach here for keys.length > 0
    }

    /**
     * 链式获取嵌套Map中的值，如果不存在则返回默认值。
     *
     * @param defaultValue 默认值
     * @param keys         键路径
     * @param <T>          返回类型
     * @return 嵌套值或默认值
     */
    public <T> T getNested(T defaultValue, String... keys) {
        try {
            T value = getNested(keys);
            return value != null ? value : defaultValue;
        } catch (IllegalArgumentException e) {
            // Log this exception if needed, but for 'get' semantics, return default
            return defaultValue;
        }
    }

    /**
     * 从多个键中获取第一个存在的值。
     *
     * @param keys 键列表
     * @param <T>  返回类型
     * @return 第一个存在的值
     * @throws java.util.NoSuchElementException 如果所有键都不存在
     */
    @SuppressWarnings("unchecked")
    public <T> T getFromAnyKey(String... keys) {
        for (String key : keys) {
            if (data.containsKey(key)) {
                return (T) get(key);
            }
        }
        throw new java.util.NoSuchElementException("No value found for any of the keys: " + String.join(", ", keys));
    }

    /**
     * 从多个键中获取第一个存在的值，如果都不存在则返回默认值。
     *
     * @param defaultValue 默认值
     * @param keys         键列表
     * @param <T>          返回类型
     * @return 第一个存在的值或默认值
     */
    @SuppressWarnings("unchecked")
    public <T> T getFromAnyKey(T defaultValue, String... keys) {
        for (String key : keys) {
            if (data.containsKey(key)) {
                return (T) get(key);
            }
        }
        return defaultValue;
    }


    @Override
    public Object put(String key, Object value) {
        return data.put(key, value);
    }

    @Override
    public Object remove(Object key) {
        return data.remove(key);
    }

    @Override
    public void putAll(Map<? extends String, ?> m) {
        data.putAll(m);
    }

    @Override
    public void clear() {
        data.clear();
    }

    @Override
    public Set<String> keySet() {
        return data.keySet();
    }

    @Override
    public Collection<Object> values() {
        // 返回包装后的值集合
        return data.values().stream().map(AdvancedMap::wrapValue).collect(Collectors.toList());
    }

    @Override
    public Set<Entry<String, Object>> entrySet() {
        // 返回包装后的Entry集合
        return data.entrySet().stream()
                .map(entry -> new AbstractMap.SimpleEntry<>(entry.getKey(), wrapValue(entry.getValue())))
                .collect(Collectors.toSet());
    }

    /**
     * 将当前AdvancedMap转换为JSON字符串。
     *
     * @return JSON字符串
     * @throws IOException 如果序列化失败
     */
    public String toJson() throws IOException {
        return JsonUtils.toJsonString(data);
    }

    /**
     * 将当前AdvancedMap转换为格式化的JSON字符串。
     *
     * @return 格式化的JSON字符串
     * @throws IOException 如果序列化失败
     */
    public String toPrettyJson() throws IOException {
        return JsonUtils.toPrettyJsonString(data);
    }

    // 实现深拷贝
    public AdvancedMap deepCopy() {
        try {
            String json = JsonUtils.toJsonString(data);
            Map<String, Object> copyData = JsonUtils.parseStringAsMap(json);
            return new AdvancedMap(copyData);
        } catch (IOException e) {
            throw new RuntimeException("Failed to deep copy AdvancedMap", e);
        }
    }

    @Override
    public String toString() {
        return data.toString();
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        AdvancedMap that = (AdvancedMap) o;
        return Objects.equals(data, that.data);
    }

    @Override
    public int hashCode() {
        return Objects.hash(data);
    }
}